#pragma once
#include "../json/json.h"
#include <memory>
#include <sstream>
#include <iostream>
#include "../common/singleton.h"

struct JsonBuilder
{
    Json::StreamWriterBuilder writerBuilder;
    Json::CharReaderBuilder readerBuilder;
    JsonBuilder()
    {
        writerBuilder["indentation"] = ""; // 压缩格式，没有换行和不必要的空白字符
    }
};

typedef Singleton<JsonBuilder> jsonBuilderInst;

std::string to_string(const Json::Value &rValue);
namespace Utils
{
    Json::Value to_json(const std::string &result);
}

inline void load_val(const Json::Value& rVal, const std::string& key, std::string& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asString();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, int& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asInt();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, unsigned int& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asUInt();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, float& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asFloat();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, double& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asDouble();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, bool& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asBool();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, long long& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asInt64();
    }
}

inline void load_val(const Json::Value& rVal, const std::string& key, unsigned long long& val)
{
    if(rVal.isMember(key) && rVal[key].isNull() == false)
	{
        val = rVal[key].asUInt64();
    }
}

inline void load_val(const Json::Value& jSrc, const std::string& key, Json::Value& jDst)
{
    if(jSrc.isMember(key) && jSrc[key].isNull() == false)
	{
        jDst[key] = jSrc[key];
    }
}

inline void concat_val(Json::Value& jDst, const Json::Value& jSrc)
{
    for (const auto& key : jSrc.getMemberNames()) {
		load_val(jSrc, key, jDst);
    }
}



/**************************** Class Attribute Json Dump And Parse *****************************************/
/**
 * @warning T must extends from common/basic_type.h::BasicType or Implemented FillInfo()
*/
template<class T>
inline void Dump(Json::Value& rValue, const T& arg)
{
    arg.FillInfo(rValue);
}
 
template<class T, typename...Args>
inline void Dump(Json::Value& rValue, const T& arg, Args... args)
{
    arg.FillInfo(rValue);
    Dump(rValue, args...);
}
 
/**
 * @warning T must extends from common/basic_type.h::BasicType or Implemented Set()
*/
template<class T>
inline void Parse(Json::Value& rValue, const T& arg)
{
    arg.Set(rValue);
}
 
template<class T, typename...Args>
inline void Parse(Json::Value& rValue, const T& arg, Args... args)
{
    arg.Set(rValue);
    Parse(rValue, args...);
}
/**************************** Class Attribute Json Dump And Parse *****************************************/
